package com.itheima.project.handler.impl;

import com.itheima.project.constant.security.OauthCacheConstant;
import com.itheima.project.constant.security.OauthConstant;
import com.itheima.project.handler.CacheTokenHandler;
import com.itheima.project.properties.SecurityProperties;
import com.itheima.project.vo.security.UserVo;
import org.redisson.api.RBucket;
import org.redisson.api.RedissonClient;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.security.oauth2.common.OAuth2AccessToken;
import org.springframework.security.oauth2.common.OAuth2RefreshToken;
import org.springframework.stereotype.Component;

import java.util.Set;
import java.util.concurrent.TimeUnit;

/**
 * @ClassName CacheTokenHandlerImpl.java
 * @Description Token缓存处理
 */
@Component
@EnableConfigurationProperties(SecurityProperties.class)
public class CacheTokenHandlerImpl implements CacheTokenHandler {

    @Autowired
    RedissonClient redissonClient;

    @Autowired
    SecurityProperties securityProperties;

    @Override
    public UserVo cacheToken(OAuth2AccessToken oAuth2AccessToken){
        //登录成功后获得oAuth2AccessToken中增强信息
        Long id = Long.valueOf(oAuth2AccessToken.getAdditionalInformation().get(OauthConstant.USER_ID_KEY).toString());
        String jti =String.valueOf(oAuth2AccessToken.getAdditionalInformation().get(OauthConstant.JTI_KEY));
        String mobile =String.valueOf(oAuth2AccessToken.getAdditionalInformation().get(OauthConstant.MOBILE_KEY));
        String openId =String.valueOf(oAuth2AccessToken.getAdditionalInformation().get(OauthConstant.OPEN_ID_KEY));
        Set<String> resources = (Set<String>) oAuth2AccessToken.getAdditionalInformation().get(OauthConstant.RESOURCS_KEY);
        Set<String> roles = (Set<String>) oAuth2AccessToken.getAdditionalInformation().get(OauthConstant.ROLES_KEY);
        String username = String.valueOf(oAuth2AccessToken.getAdditionalInformation().get(OauthConstant.USER_NAME_KEY));
        String clientId = String.valueOf(oAuth2AccessToken.getAdditionalInformation().get(OauthConstant.CLIENT_ID_KEY));
        String enterpriseId = String.valueOf(oAuth2AccessToken.getAdditionalInformation().get(OauthConstant.ENTERPRISE_ID_KEY));
        //设置accessToken到redis，获得时使用jti获取
        String accessToken = oAuth2AccessToken.getValue();
        RBucket<String> accessTokenBucket = redissonClient.getBucket(OauthCacheConstant.ACCESS_TOKEN + jti);
        long accessTokenExpiresIn = Long.valueOf(oAuth2AccessToken.getAdditionalInformation().get(OauthConstant.EXPIRES_IN_KEY).toString());
        accessTokenBucket.set(accessToken,accessTokenExpiresIn, TimeUnit.SECONDS);
        //设置refreshToken到redis，获得时使用jti获取
        OAuth2RefreshToken oAuth2RefreshToken = oAuth2AccessToken.getRefreshToken();
        String refreshToken = oAuth2RefreshToken.getValue();
        long refreshTokenExpiresIn = securityProperties.getRefreshTokenValiditySeconds();
        RBucket<String> refreshTokenBucket = redissonClient.getBucket(OauthCacheConstant.REFRESH_TOKEN + jti);
        refreshTokenBucket.set(refreshToken,refreshTokenExpiresIn, TimeUnit.SECONDS);
        //绑定username与jti,用于剔除设置
        RBucket<String> usernameBucket = redissonClient.getBucket(OauthCacheConstant.BIND_USERNAME + username);
        usernameBucket.set(jti,refreshTokenExpiresIn, TimeUnit.SECONDS);
        //构建返回对象
        UserVo userVo = UserVo.builder()
                .id(id)
                .enterpriseId(Long.valueOf(enterpriseId))
                .clientId(clientId).username(username)
                .jti(jti)
                .resources(resources)
                .roles(roles)
                .openId(openId)
                .mobile(mobile)
                .build();
        //设置userVo到redis，获得时候使用jti获得
        RBucket<UserVo> jtiUserBucket = redissonClient.getBucket(OauthCacheConstant.JTI_USER + jti);
        jtiUserBucket.set(userVo,accessTokenExpiresIn, TimeUnit.SECONDS);
        return userVo;
    }

    @Override
    public Boolean deleteToken(String jti) {
        RBucket<String> accessTokenBucket = redissonClient.getBucket(OauthCacheConstant.ACCESS_TOKEN + jti);
        boolean deleteAccessToken = accessTokenBucket.delete();
        RBucket<String> refreshTokenBucket = redissonClient.getBucket(OauthCacheConstant.REFRESH_TOKEN + jti);
        boolean deleteRefreshToken = refreshTokenBucket.delete();
        if (deleteAccessToken&&deleteRefreshToken){
            return true;
        }
        return false;
    }

}
